package com.dongni.tools;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;

/**
 * 时间转换工具类
 */
public class DateUtils {

    private static String[] parsePatterns = {
            "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM",
            "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM",
            "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"};

    private DateUtils() {
        throw new UnsupportedOperationException("u can't instantiate me...");
    }

    private static String TIME_ZONE_BEIJING = "GMT+08";
    private static TimeZone sTimeZone = TimeZone.getTimeZone(TIME_ZONE_BEIJING);

    /**
     * 得到当前日期字符串 格式（yyyy-MM-dd）
     */
    public static String getDate() {
        return getDate("yyyy-MM-dd");
    }

    /**
     * 得到当前日期字符串 格式（yyyy-MM-dd） pattern可以为："yyyy-MM-dd" "HH:mm:ss" "E"
     */
    public static String getDate(String pattern) {
        return formatDate(new Date(), pattern);
    }

    /**
     * 得到日期字符串 默认格式（yyyy-MM-dd） pattern可以为："yyyy-MM-dd" "HH:mm:ss" "E"
     */
    public static String formatDate(Date date, Object... pattern) {
        if (date == null) {
            return null;
        }
        SimpleDateFormat format;
        String formatDate;
        if (pattern != null && pattern.length > 0) {
            format = new SimpleDateFormat(pattern[0].toString());
            format.setTimeZone(sTimeZone);
            formatDate = format.format(date);
        } else {
            format = new SimpleDateFormat("yyyy-MM-dd HH:mm");
            format.setTimeZone(sTimeZone);
            formatDate = format.format(date);
        }
        return formatDate;
    }

    /**
     * 得到日期时间字符串，转换格式（yyyy-MM-dd HH:mm:ss）
     */
    public static String formatDateTime(Date date) {
        return formatDate(date, "yyyy-MM-dd HH:mm:ss");
    }

    /**
     * 得到当前时间字符串 格式（HH:mm:ss）
     */
    public static String getTime() {
        return formatDate(new Date(), "HH:mm:ss");
    }

    /**
     * 得到当前日期和时间字符串 格式（yyyy-MM-dd HH:mm:ss）
     */
    public static String getDateTime() {
        return formatDate(new Date(), "yyyy-MM-dd HH:mm:ss");
    }

    /**
     * 得到当前年份字符串 格式（yyyy）
     */
    public static String getYear() {
        return formatDate(new Date(), "yyyy");
    }

    /**
     * 得到当前月份字符串 格式（MM）
     */
    public static String getMonth() {
        return formatDate(new Date(), "MM");
    }

    /**
     * 得到当天字符串 格式（dd）
     */
    public static String getDay() {
        return formatDate(new Date(), "dd");
    }

    /**
     * 得到当前星期字符串 格式（E）星期几
     */
    public static String getWeek() {
        return formatDate(new Date(), "E");
    }


    /**
     * 获取过去的天数
     *
     * @param date
     * @return
     */
    public static long pastDays(Date date) {
        long t = new Date().getTime() - date.getTime();
        return t / (24 * 60 * 60 * 1000);
    }

    /**
     * 获取过去的小时
     *
     * @param date
     * @return
     */
    public static long pastHour(Date date) {
        long t = new Date().getTime() - date.getTime();
        return t / (60 * 60 * 1000);
    }

    /**
     * 获取过去的分钟
     *
     * @param date
     * @return
     */
    public static long pastMinutes(Date date) {
        long t = new Date().getTime() - date.getTime();
        return t / (60 * 1000);
    }

    /**
     * 转换为时间（天,时:分:秒.毫秒）
     *
     * @param timeMillis
     * @return
     */
    public static String formatDateTime(long timeMillis) {
        long day = timeMillis / (24 * 60 * 60 * 1000);
        long hour = (timeMillis / (60 * 60 * 1000) - day * 24);
        long min = ((timeMillis / (60 * 1000)) - day * 24 * 60 - hour * 60);
        long s = (timeMillis / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - min * 60);
        long sss = (timeMillis - day * 24 * 60 * 60 * 1000 - hour * 60 * 60 * 1000 - min * 60 * 1000 - s * 1000);
        return (day > 0 ? day + "," : "") + hour + ":" + min + ":" + s + "." + sss;
    }

    /**
     * 获取两个日期之间的天数
     * @param before
     * @param after
     * @return
     */
    public static double getDistanceOfTwoDate(Date before, Date after) {
        long beforeTime = before.getTime();
        long afterTime = after.getTime();
        return (afterTime - beforeTime) / (1000 * 60 * 60 * 24);
    }

    /**
     * 获取当前月第一天
     * @param pattern
     * @return
     */
    public static String getFirstDayOfMonth(String pattern) {
        SimpleDateFormat format = new SimpleDateFormat(pattern);
        format.setTimeZone(sTimeZone);
        Calendar c = Calendar.getInstance(sTimeZone);
        c.add(Calendar.MONTH, 0);
        c.set(Calendar.DAY_OF_MONTH, 1);//设置为1号,当前日期既为本月第一天
        return format.format(c.getTime());
    }

    /**
     * 将时间转换为时间戳
     *
     * @param s       2019-06-05 13:13
     * @param pattern yyyy-MM-dd HH:mm
     */
    public static String dateToStamp(String s, String pattern) throws ParseException {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern);
        simpleDateFormat.setTimeZone(sTimeZone);
        Date date = simpleDateFormat.parse(s);
        long ts = date.getTime();
        return String.valueOf(ts);
    }

    /**
     * 将时间转换为时间戳
     *
     * @param s       2019-06-05 13:13
     * @param pattern yyyy-MM-dd HH:mm
     */
    public static long dateToStamL(String s, String pattern) throws ParseException {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern);
        simpleDateFormat.setTimeZone(sTimeZone);
        Date date = simpleDateFormat.parse(s);
        long ts = date.getTime();
        return ts;
    }

    /**
     * 将时间转换为时间戳
     *
     * @param s       2019-06-05 13:13
     * @param pattern yyyy-MM-dd HH:mm
     */
    public static long dateToStamLS(String s, String pattern) throws ParseException {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern);
        simpleDateFormat.setTimeZone(sTimeZone);
        Date date = simpleDateFormat.parse(s);
        long ts = date.getTime();
        return ts / 1000;
    }


    /*
     * 将时间戳转换为时间
     */
    public static String stampToDate(String s) {
        return stampToDate(s, "yyyy-MM-dd HH:mm");
    }

    /*
     * 将秒数时间戳转换为时间
     */
    public static String secondStampToDate(String s, String pattern) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern);
        simpleDateFormat.setTimeZone(sTimeZone);
        long lt = new Long(s) * 1000;
        Date date = new Date(lt);
        return simpleDateFormat.format(date);
    }

    /*
     * 将秒数时间戳转换为时间
     */
    public static String secondStampToDate(long s, String pattern) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern);
        simpleDateFormat.setTimeZone(sTimeZone);
        long lt = new Long(s) * 1000;
        Date date = new Date(lt);
        return simpleDateFormat.format(date);
    }

    /*
     * 将毫秒数时间戳转换为时间
     */
    public static String milliSecondStampToDate(long s, String pattern) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern);
        simpleDateFormat.setTimeZone(sTimeZone);
        long lt = new Long(s);
        Date date = new Date(lt);
        return simpleDateFormat.format(date);
    }

    /*
     * 将时间戳转换为时间
     */
    public static String stampToDate(String s, String pattern) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern);
        simpleDateFormat.setTimeZone(sTimeZone);
        Date date = new Date(new Long(s));
        return simpleDateFormat.format(date);
    }

    /*
     * 将时间戳转换为时间
     */
    public static String stampToDate(long s, String pattern) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern);
        simpleDateFormat.setTimeZone(sTimeZone);
        Date date = new Date(s);
        return simpleDateFormat.format(date);
    }

    /*
     * 将当前时间转换成年-月-日,如：2018-7-12
     */
    public static String stampToCurrDayDate(String pattern) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern);
        simpleDateFormat.setTimeZone(sTimeZone);
        Date date = new Date(System.currentTimeMillis());
        return simpleDateFormat.format(date);
    }

    /*
     * 将当前时间转换成年-月-日，如：2018年7月12日
     */
    public static String stampToCurrChDayDate() {
        return stampToCurrDayDate("yyyy年MM月dd日");
    }

    /*
     * 将时间戳转换为时间
     */
    public static String stampToDateL(long s) {
        return stampToDate(s,"yyyy-MM-dd HH:mm");
    }


    /***
     * 获取当下"天"的开始时间戳
     * @return 秒值
     */
    public static long getDayStartTime() {
        Calendar c = Calendar.getInstance(sTimeZone);
        c.set(Calendar.HOUR_OF_DAY, 0);
        c.set(Calendar.MINUTE, 0);
        c.set(Calendar.SECOND, 0);
        return c.getTimeInMillis() / 1000;
    }

    /***
     * 获取当下"天"的结束时间戳
     * @return 秒值
     */
    public static long getDayEndTime() {
        Calendar c = Calendar.getInstance(sTimeZone);
        c.set(Calendar.HOUR_OF_DAY, 23);
        c.set(Calendar.MINUTE, 59);
        c.set(Calendar.SECOND, 59);
        return c.getTimeInMillis() / 1000;
    }

    /**
     * 获取当下"周"的开始时间戳
     *
     * @return 秒值
     */
    public static long getWeekStartTime() {
        Calendar c = Calendar.getInstance(sTimeZone);
        c.set(Calendar.DAY_OF_WEEK, c.getFirstDayOfWeek());
        c.set(Calendar.HOUR_OF_DAY, 0);
        c.set(Calendar.MINUTE, 0);
        c.set(Calendar.SECOND, 0);
        return c.getTimeInMillis() / 1000;
    }

    /**
     * 获取当下"周"的开始时间戳
     *
     * @return 秒值
     */
    public static long getWeekStartTimeFrmMonday() {
        Calendar c = Calendar.getInstance(sTimeZone);
        c.setFirstDayOfWeek(Calendar.MONDAY);
        c.set(Calendar.DAY_OF_WEEK, c.getFirstDayOfWeek());
        c.set(Calendar.HOUR_OF_DAY, 0);
        c.set(Calendar.MINUTE, 0);
        c.set(Calendar.SECOND, 0);
        return c.getTimeInMillis() / 1000;
    }

    /**
     * 获取当下"周"的结束时间戳
     *
     * @return 秒值
     */
    public static long getWeekEndTime() {
        Calendar c = Calendar.getInstance(sTimeZone);
        c.set(Calendar.DAY_OF_WEEK, c.getFirstDayOfWeek() + 6);
        c.set(Calendar.HOUR_OF_DAY, 23);
        c.set(Calendar.MINUTE, 59);
        c.set(Calendar.SECOND, 59);
        return c.getTimeInMillis() / 1000;
    }

    /**
     * 获取当下"周"的结束时间戳
     *
     * @return 秒值
     */
    public static long getWeekEndTimeFrmMonday() {
        Calendar c = Calendar.getInstance(sTimeZone);
        c.setFirstDayOfWeek(Calendar.MONDAY);
        c.set(Calendar.DAY_OF_WEEK, c.getFirstDayOfWeek() + 6);
        c.set(Calendar.HOUR_OF_DAY, 23);
        c.set(Calendar.MINUTE, 59);
        c.set(Calendar.SECOND, 59);
        return c.getTimeInMillis() / 1000;
    }

    /**
     * 获取当下对应"月"的开始时间戳
     *
     * @return
     */
    public static long getMonthStartTime() {
        Calendar c = Calendar.getInstance(sTimeZone);
        c.set(Calendar.MONTH, c.get(Calendar.MONTH));
        c.set(Calendar.DAY_OF_MONTH, 1);//设置为1号,当前日期既为本月第一天
        c.set(Calendar.HOUR_OF_DAY, 0);
        c.set(Calendar.MINUTE, 0);
        c.set(Calendar.SECOND, 0);
        return c.getTimeInMillis() / 1000;
    }

    /**
     * 获取当下对应"月"的结束时间戳
     *
     * @return
     */
    public static long getMonthEndTime() {
        Calendar c = Calendar.getInstance(sTimeZone);
        c.set(Calendar.MONTH, c.get(Calendar.MONTH));
        c.set(Calendar.DAY_OF_MONTH, c.getActualMaximum(Calendar.DAY_OF_MONTH));
        c.set(Calendar.HOUR_OF_DAY, 23);
        c.set(Calendar.MINUTE, 59);
        c.set(Calendar.SECOND, 59);
        return c.getTimeInMillis() / 1000;
    }

    /**
     * 毫秒转秒
     */
    public static long milli2Second(long millisecond) {
        return millisecond / 1000;
    }

    /**
     * 获取一年的第一天 时间戳
     *
     * @param year
     * @return
     */
    public static long firstYearmilli(int year) {
        Calendar calendar = Calendar.getInstance(sTimeZone);
        calendar.clear();
        calendar.set(Calendar.YEAR, year);
        return calendar.getTimeInMillis() / 1000;
    }

    /**
     * 获取一年的最后一天 最后一秒
     * @param year
     * @return
     */
    public static long lastYearmilli(int year) {
        Calendar calendar = Calendar.getInstance(sTimeZone);
        calendar.clear();
        calendar.set(Calendar.YEAR, year);
        calendar.roll(Calendar.DAY_OF_YEAR, -1);
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        return calendar.getTimeInMillis() / 1000;
    }

    /**
     * 获取某年某月的开始时间戳
     *
     * @param year  年份
     * @param month 月份 (当前月份为多少传多少)
     * @return
     */
    public static long firstMonthmilli(int year, int month) {
        Calendar calendar = Calendar.getInstance(sTimeZone);
        calendar.clear();
        calendar.set(Calendar.YEAR, year);
        calendar.set(Calendar.MONTH, month - 1);
        return calendar.getTimeInMillis() / 1000;
    }

    /**
     * 获取某年某月的最后一秒
     *
     * @param year  年份
     * @param month 月份 (当前月份为多少传多少)
     * @return
     */
    public static long lastMonthmilli(int year, int month) {
        Calendar calendar = Calendar.getInstance(sTimeZone);
        calendar.clear();
        calendar.set(Calendar.YEAR, year);
        calendar.set(Calendar.MONTH, month - 1);
        calendar.roll(Calendar.DAY_OF_MONTH, -1);
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        return calendar.getTimeInMillis() / 1000;
    }

    /**
     * 获取某年某月的具体天数
     *
     * @param year
     * @param month
     * @return
     */
    public static int monthDay(int year, int month) {
        Calendar calendar = Calendar.getInstance(sTimeZone);
        calendar.clear();
        calendar.set(Calendar.YEAR, year);
        calendar.set(Calendar.MONTH, month - 1);
        return calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
    }


    /**
     * 获取某年某月某日的开始时间戳
     *
     * @param year  年份
     * @param month 月份 (当前月份为多少传多少)
     * @return
     */
    public static long firstMonthDaymilli(int year, int month, int day) {
        Calendar calendar = Calendar.getInstance(sTimeZone);
        calendar.clear();
        calendar.set(Calendar.YEAR, year);
        calendar.set(Calendar.MONTH, month - 1);
        calendar.set(Calendar.DAY_OF_MONTH, day);
        return calendar.getTimeInMillis() / 1000;
    }

    /**
     * 获取某年某月某日的最后一秒
     *
     * @param year  年份
     * @param month 月份 (当前月份为多少传多少)
     * @return
     */
    public static long lastMonthDaymilli(int year, int month, int day) {
        Calendar calendar = Calendar.getInstance(sTimeZone);
        calendar.clear();
        calendar.set(Calendar.YEAR, year);
        calendar.set(Calendar.MONTH, month - 1);
        calendar.set(Calendar.DAY_OF_MONTH, day);
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);

        return calendar.getTimeInMillis() / 1000;
    }


    /**
     * 某年的第几周第一天的时间戳
     *
     * @param year 年份
     * @param week 周
     * @return
     */
    public static long weekFirstMilli(int year, int week) {
        week = week - 1;
        Calendar calendar = Calendar.getInstance(sTimeZone);
        calendar.clear();
        calendar.set(Calendar.YEAR, year);
        calendar.set(Calendar.MONTH, Calendar.JANUARY);
        calendar.set(Calendar.DATE, 1);

        calendar.add(Calendar.DATE, week * 7);
//        calendar.setFirstDayOfWeek(Calendar.SUNDAY);
        calendar.setFirstDayOfWeek(Calendar.MONDAY);
        calendar.set(Calendar.DAY_OF_WEEK,
                calendar.getFirstDayOfWeek());
        return calendar.getTimeInMillis() / 1000;
    }

    /**
     * 某年的第几周最后一天的时间戳
     *
     * @param year
     * @param week
     * @return
     */
    public static long weekLastMilli(int year, int week) {
        week = week - 1;
        Calendar calendar = Calendar.getInstance(sTimeZone);
        calendar.set(Calendar.YEAR, year);
        calendar.set(Calendar.MONTH, Calendar.JANUARY);
        calendar.set(Calendar.DATE, 1);
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);

        calendar.add(Calendar.DATE, week * 7);
//        calendar.setFirstDayOfWeek(Calendar.SUNDAY);
        calendar.setFirstDayOfWeek(Calendar.MONDAY);
        calendar.set(Calendar.DAY_OF_WEEK,
                calendar.getFirstDayOfWeek() + 6); // Saturday
        return calendar.getTimeInMillis() / 1000;
    }

    public static String weekDuringStr(int year, int week) {

        StringBuilder builder = new StringBuilder();
        week = week - 1;
        Calendar calendar = Calendar.getInstance(sTimeZone);
        calendar.clear();
        calendar.set(Calendar.YEAR, year);
        calendar.set(Calendar.MONTH, Calendar.JANUARY);
        calendar.set(Calendar.DATE, 1);

        calendar.add(Calendar.DATE, week * 7);
//        calendar.setFirstDayOfWeek(Calendar.SUNDAY);
        calendar.setFirstDayOfWeek(Calendar.MONDAY);
        calendar.set(Calendar.DAY_OF_WEEK,
                calendar.getFirstDayOfWeek());

        builder.append(stampToDate(String.valueOf(calendar.getTimeInMillis()), "MM月dd日"));

        builder.append("～");
        calendar.set(Calendar.DAY_OF_WEEK,
                calendar.getFirstDayOfWeek() + 6); // Saturday
        builder.append(stampToDate(String.valueOf(calendar.getTimeInMillis()), "MM月dd日"));

        return builder.toString();
    }

    /**
     * 获取时间戳有多少个周
     *
     * @param mill
     * @return
     */
    public static int getWeekCount(long mill) {
        Calendar calendar = Calendar.getInstance(sTimeZone);
//        calendar.setFirstDayOfWeek(Calendar.SUNDAY);
        calendar.setFirstDayOfWeek(Calendar.MONDAY);
        Date date = new Date();
        date.setTime(mill);
        calendar.setTime(date);
        return calendar.get(Calendar.WEEK_OF_YEAR);
    }

    /**
     * 获取季度的起始时间
     *
     * @param year
     * @param quarter
     * @return
     */
    public static long getQuarterFirstMill(int year, int quarter) {
        int month = quarter * 3 - 2;
        return firstMonthmilli(year, month);
    }

    /**
     * 获取季度的结束时间
     *
     * @param year
     * @param quarter
     * @return
     */
    public static long getQuarterLastMill(int year, int quarter) {
        int month = quarter * 3;
        return lastMonthmilli(year, month);
    }
}
